package com.lyn.seckill.controller;

import com.alibaba.druid.util.StringUtils;
import com.lyn.seckill.common.ResponseReturnType;
import com.lyn.seckill.common.error.BusinessException;
import com.lyn.seckill.common.error.EnumBusinessError;
import com.lyn.seckill.controller.viewovject.UserVO;
import com.lyn.seckill.service.UserService;
import com.lyn.seckill.service.model.UserModel;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import sun.misc.BASE64Encoder;

import javax.servlet.http.HttpServletRequest;
import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Random;

@Controller
@CrossOrigin(allowCredentials = "true",allowedHeaders = "*")
// allowedHeaders:允许跨域传输所有的header参数，将用于使用token放入header域做session共享的跨域请求！
// allowCredentials:需要配合前端xhrFields授信后使得session跨域共享！
public class UserController extends BaseController{

    private final UserService userService;
    private final HttpServletRequest httpServletRequest;
    public UserController(UserService userService, HttpServletRequest httpServletRequest) {
        this.userService = userService;
        this.httpServletRequest = httpServletRequest;
    }

    /**
     * 短信验证，后续用阿里云短信业务微服务替代
     * @param telephone
     * @return
     */
    @PostMapping(value = "/getOtp",consumes = {CONTENT_TYPE_FORMED})
    @ResponseBody
    public ResponseReturnType getOtp(@RequestParam("telephone") String telephone) {
        // 需要按照一定的规则生成OTP验证码
        Random random = new Random();
        int randomInt = random.nextInt(9999);
        randomInt += 10000;
        String otpCode = String.valueOf(randomInt);

        // 将OTP验证码同对应用户的手机号关联，使用HttpSession的方式绑定他的手机号与OTPCode
        httpServletRequest.getSession().setAttribute(telephone,otpCode);

        // 将OTP验证码通过短信通道发送给用户
        System.out.println("telephone = " + telephone + " & otpCode = " + otpCode);
        return ResponseReturnType.create(null);
    }

    /**
     * 登录
     * @param telephone
     * @param encryptPassword
     * @return
     * @throws BusinessException
     * @throws UnsupportedEncodingException
     * @throws NoSuchAlgorithmException
     */
    @PostMapping(value = "/login",consumes = {CONTENT_TYPE_FORMED})
    @ResponseBody
    public ResponseReturnType login(@RequestParam("telephone")String telephone,
                                    @RequestParam("password")String encryptPassword) throws BusinessException, UnsupportedEncodingException, NoSuchAlgorithmException {
        // 入参校验
        if (org.apache.commons.lang3.StringUtils.isEmpty(telephone) ||
                org.apache.commons.lang3.StringUtils.isEmpty(encryptPassword)) {
            throw new BusinessException(EnumBusinessError.PARAMETER_VALIDATION_ERROR);
        }
        // 用户登录服务，用来校验用户登录是否合法
        UserModel userModel = userService.validateLogin(telephone, this.EncodeByMd5(encryptPassword));

        // 加入到用户登录成功的session内
        this.httpServletRequest.getSession().setAttribute(EnumBusinessError.IS_LOGIN,true);
        this.httpServletRequest.getSession().setAttribute(EnumBusinessError.LOGIN_USER,userModel);
        return ResponseReturnType.create(null);
    }


    /**
     * 注册
     * @param otpCode
     * @param telephone
     * @param name
     * @param gender
     * @param age
     * @param encryptPassword
     * @return
     * @throws BusinessException
     */
    @PostMapping(value = "/register",consumes = {CONTENT_TYPE_FORMED})
    @ResponseBody
    public ResponseReturnType register(@RequestParam("otpCode") String otpCode,
                                       @RequestParam("telephone")String telephone,
                                       @RequestParam("name")String name,
                                       @RequestParam("gender")Boolean gender,
                                       @RequestParam("age")Integer age,
                                       @RequestParam("password")String encryptPassword) throws BusinessException, UnsupportedEncodingException, NoSuchAlgorithmException {
        UserModel userModel = new UserModel(null,name,gender,age,telephone,"byPhone","",encryptPassword);
        System.out.println(userModel);
        System.out.println(otpCode);
        // 验证手机号和对应的OTPCode是否符合
        String inSessionOtpCode = (String) this.httpServletRequest.getSession().getAttribute(userModel.getTelephone());
        if (!StringUtils.equals(otpCode,inSessionOtpCode)) {
            throw new BusinessException(EnumBusinessError.PARAMETER_VALIDATION_ERROR,"短信验证码不符合");
        }
        // 用户的注册流程
        if (!org.apache.commons.lang3.StringUtils.isNotBlank(userModel.getEncryptPassword())) {
            throw new BusinessException(EnumBusinessError.PARAMETER_VALIDATION_ERROR,"密码必填");
        }
        userModel.setEncryptPassword(this.EncodeByMd5(userModel.getEncryptPassword()));

        userService.register(userModel);
        return ResponseReturnType.create(null);
    }

    /**
     * 获取用户信息
     * @param id
     * @return
     * @throws BusinessException
     */
    @GetMapping("/get/{id}")
    @ResponseBody
    public ResponseReturnType getUser(@PathVariable("id") Integer id) throws BusinessException {
        // 调用service服务获取对应id的用户对象并返回给前端
        UserModel userById = userService.getUserById(id);

        // 若获取的对应用户信息不存在
        if (userById == null) {
            throw new BusinessException(EnumBusinessError.USER_NOT_EXIST);
        }

        // 将核心领域模型用户对象转化为可供前端UI使用的VO
        UserVO userVO = convertFromVieObject(userById);
        return ResponseReturnType.create(userVO);
    }

    /**
     * 将核心领域模型用户对象（ModelObject，MO）转化为可供前端UI使用的视图对象（ViewObject，VO）
     * @param userModel
     * @return
     */
    private UserVO convertFromVieObject(UserModel userModel) {
        if (userModel == null) {
            return null;
        }
        UserVO userVO = new UserVO();
        BeanUtils.copyProperties(userModel,userVO);
        return userVO;
    }

    /**
     * MD5加密
     * @param str
     * @return
     * @throws UnsupportedEncodingException
     * @throws NoSuchAlgorithmException
     */
    public String EncodeByMd5(String str) throws UnsupportedEncodingException, NoSuchAlgorithmException {
        return new BASE64Encoder().encode(MessageDigest.getInstance("MD5").digest(str.getBytes("UTF-8")));
    }

}
